/*
 * @Date: 2023-05-07 16:33:28
 * @LastEditTime: 2023-09-14 12:02:56
 * @FilePath: /wkw/src/views/addLiquidity/useLiquidity.ts
 * 介绍:
 */
import {
  sdkGetLpAddress,
  sdkGetReserves,
  sdkLpTotalSupply,
  sdkFindTokenBalance,
  sdkDecimal,
  sdkGetLpToken0,
} from "@@/sdk/web3Eth";
import { funDelay } from "@@/utils/tools/function";
import { parseBalance } from "@@/sdk/index";
import { divide, multiply } from "mathjs";
import useUserinfoStore from "@@/store/useUserinfoStore";
/**最大重试次数 */
const MAX_RETRY = 5;

export function useLiquidity() {
  /**工厂地址 */
  const lpPool = reactive<{
    contract_addr?: string;
    totalValue?: string;
    /**我的流动性总量 */
    balanceValue?: string;
    format?: number;
    total0Value?: string;
    total1Value?: string;
    /**是否矿池创始人 */
    isOriginator: boolean;
    coin0?: CoinPay;
    coin1?: CoinPay;
  }>({
    /**添加流动性比率两输入框计算比率，to币种除from币种 */
    isOriginator: false,
  });
  let factoryAddress = "0x5757371414417b8c6caad45baef941abc7d3ab32";
  /**获取lp矿池地址 */
  async function getLpAddress(
    coin0: CoinPay,
    coin1: CoinPay,
    /**工厂地址 */
    _factoryAddress: string = factoryAddress,
    count = 1
  ): Promise<string> {
    const lp_contract = useUserinfoStore().userinfo?.set.lp_contract!;
    console.log("服务器lp合约", lp_contract);
    if (lp_contract) {
      factoryAddress = _factoryAddress;
      return (lpPool.contract_addr = lp_contract);
    }
    const addrRes = await sdkGetLpAddress(
      [coin0.contract_addr!, coin1.contract_addr!],
      _factoryAddress
    );
    if (!addrRes.status) {
      if (count > MAX_RETRY) return Promise.reject("获取lp合约失败");
      return await funDelay(
        getLpAddress,
        [coin0, coin1, _factoryAddress, ++count],
        5000
      );
    }
    factoryAddress = _factoryAddress;
    lpPool.contract_addr = addrRes.data!;
    return addrRes.data!;
  }
  async function setOption(
    coin0: CoinPay,
    coin1: CoinPay,
    /**工厂地址 */
    _factoryAddress?: string
  ) {
    if (coin0.contract_addr === coin1.contract_addr) return;
    const res = await getLpAddress(coin0, coin1, _factoryAddress);
    await setLpTokes(res, [coin0, coin1]);
  }

  /**设置lp币种 */
  async function setLpTokes(
    address: string,
    coins: [CoinPay, CoinPay],
    count = 1
  ): Promise<boolean> {
    //*传入的币相同则不操作
    if (
      (lpPool.coin0?.contract_addr === coins[0].contract_addr &&
        lpPool.coin1?.contract_addr === coins[1].contract_addr) ||
      (lpPool.coin0?.contract_addr === coins[1].contract_addr &&
        lpPool.coin1?.contract_addr === coins[0].contract_addr)
    ) {
      return false;
    }

    const res = await sdkGetLpToken0(address);
    if (!res.status) {
      if (count > MAX_RETRY) return Promise.reject("获取币种位置失败");
      return funDelay(setLpTokes, [address, coins, ++count], 5000);
    }
    if (Number(res.data) !== Number(coins[0]?.contract_addr)) coins.reverse();

    lpPool.coin0 = coins[0];
    lpPool.coin1 = coins[1];

    return true;
  }
  //* 功能函数
  /**获取供应(支付)比率 */
  async function getRatio() {
    const totalRes = await sdkGetReserves(lpPool.contract_addr!);
    if (!totalRes.status) return;
    const [total0, total1] = totalRes.data!;
    if (total1 === total0) lpPool.isOriginator = true;
    lpPool.total0Value = total0;
    lpPool.total1Value = total1;
    return addRatio.value;
  }
  /**获取lp矿池总量 */
  async function getTotalValue() {
    const res = await sdkLpTotalSupply(lpPool.contract_addr!);
    if (!res.status) return;
    return (lpPool.totalValue = res.data!);
  }
  /**两输入框计算比率，to币种除from币种 */
  const addRatio = computed(() =>
    divide(Number(lpPool.total1Value), Number(lpPool.total0Value))
  );
  /**获取我的流动性总量 */
  async function getBalanceValue() {
    const res = await sdkFindTokenBalance(lpPool.contract_addr!, 0);
    if (!res.status) return;
    return (lpPool.balanceValue = String(res.data!));
  }
  /**获取lp代币精度 */
  async function getDecimal() {
    const res = await sdkDecimal(lpPool.contract_addr!);
    if (!res.status) return;
    return (lpPool.format = res.data!);
  }
  /**已处理精度的lp矿池数量 */
  const total = computed(() =>
    parseBalance(lpPool.totalValue, lpPool.format || 0)
  );
  /**已处理精度的我的流动性总量 */
  const balance = computed(() =>
    parseBalance(lpPool.balanceValue, lpPool.format || 0)
  );
  const removleRatio = computed(() =>
    divide(Number(lpPool.balanceValue), Number(lpPool.totalValue))
  );
  /**计算我的流动性总量 */
  const balance0 = computed(() =>
    parseBalance(
      multiply(Number(lpPool.total0Value), removleRatio.value),
      lpPool.coin0?.format!
    )
  );
  /**我的流动性总量 */
  const balance1 = computed(() =>
    parseBalance(
      multiply(Number(lpPool.total1Value), removleRatio.value),
      lpPool.coin1?.format!
    )
  );
  /**计算流动池流动性总量 */
  const total0 = computed(() =>
    parseBalance(Number(lpPool.total0Value), lpPool.coin0?.format!)
  );
  /**计算流动池流动性总量 */
  const total1 = computed(() =>
    parseBalance(Number(lpPool.total1Value), lpPool.coin1?.format!)
  );
  return {
    lpPool,
    getRatio,
    getLpAddress,
    setOption,
    getBalanceValue,
    getDecimal,
    getTotalValue,
    total,
    balance,
    removleRatio,
    balance0,
    balance1,
    addRatio,
    total1,
    total0,
  };
}

export interface UseLiquidityRes extends ReturnType<typeof useLiquidity> {}
